<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>查询规划</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="SECT1">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="runtime-config-wal.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="runtime-config.html">快退</a></td><td width="60%" align="center" valign="bottom">章17. 服务器配置</td><td width="10%" align="right" valign="top"><a href="runtime-config.html">快进</a></td><td width="10%" align="right" valign="top"><a href="runtime-config-logging.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<div class="SECT1"><h1 class="SECT1"><a name="RUNTIME-CONFIG-QUERY">17.6. 查询规划</a></h1>
<div class="SECT2"><h2 class="SECT2"><a name="RUNTIME-CONFIG-QUERY-ENABLE">17.6.1. 规划器方法配置</a></h2>
<p>这些配置参数提供了影响查询优化器选择查询规划的原始方法。如果优化器为特定的查询选择的缺省规划并不是最优，那么我们就可以通过使用这些配置参数强制优化器选择一个更好的规划来临时解决这个问题。不过，永久地关闭这些设置几乎从不是个好主意。更好的改善优化器选择规划的方法包括调节<a href="runtime-config-query.html#RUNTIME-CONFIG-QUERY-CONSTANTS"><i>规划器开销常量</i></a>、更频繁运行 <a href="sql-analyze.html"><i>ANALYZE</i></a>、增大配置参数 <a href="runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET">default_statistics_target</a> 的值、使用 <tt class="COMMAND">ALTER TABLE SET STATISTICS</tt> 为某个字段增加收集的统计信息。</p>
<div class="VARIABLELIST">
<dl>
<dt><a name="GUC-ENABLE-BITMAPSCAN"></a><tt class="VARNAME">enable_bitmapscan</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对位图扫描规划类型的使用。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-HASHAGG"></a><tt class="VARNAME">enable_hashagg</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对 Hash 聚集规划类型的使用。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-HASHJOIN"></a><tt class="VARNAME">enable_hashjoin</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对 Hash 连接规划类型的使用。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-INDEXSCAN"></a><tt class="VARNAME">enable_indexscan</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对索引扫描规划类型的使用。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-MERGEJOIN"></a><tt class="VARNAME">enable_mergejoin</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对融合连接规划类型的使用。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-NESTLOOP"></a><tt class="VARNAME">enable_nestloop</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对嵌套循环连接规划类型的使用。我们不可能完全消除嵌套循环连接，但是把这个变量关闭就会让规划器在存在其它方法的时候优先选择其它方法。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-SEQSCAN"></a><tt class="VARNAME">enable_seqscan</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对顺序扫描规划类型的使用。我们不可能完全消除顺序扫描，但是把这个变量关闭会让规划器在存在其它方法的时候优先选择其它方法。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-SORT"></a><tt class="VARNAME">enable_sort</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器使用明确的排序步骤。我们不可能完全消除明确的排序，但是把这个变量关闭可以让规划器在存在其它方法的时候优先选择其它方法。缺省是 <tt class="LITERAL">on</tt></p></dd>
<dt><a name="GUC-ENABLE-TIDSCAN"></a><tt class="VARNAME">enable_tidscan</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭规划器对 TID 扫描规划类型的使用。缺省是 <tt class="LITERAL">on</tt></p></dd>
</dl>
</div>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="RUNTIME-CONFIG-QUERY-CONSTANTS">17.6.2. 规划器开销常量</a></h2>
<p>本节中描述的<i class="FIRSTTERM">开销</i>可以按照任意标准度量。我们只关心其相对值，因此以相同的系数缩放它们将不会对规划器产生任何影响。传统上，它们以抓取顺序页的开销作为基准单位。也就是说将 <tt class="VARNAME">seq_page_cost</tt> 设为 <tt class="LITERAL">1.0</tt> ，同时其它开销参数对照它来设置。当然你也可以使用其它基准，比如以毫秒计的实际执行时间。</p>
<div class="NOTE">
<blockquote class="NOTE">
<p><b>【注意】</b>糟糕的是，现在还没有定义得很合理的方法来判断下面出现的"开销"变量族的理想数值。它们最好按照某个特定安装的平均查询开销来衡量。这意味着仅仅根据很少量的试验结果来修改它们是很危险的。</p>
</blockquote>
</div>
<div class="VARIABLELIST">
<dl>
<dt><a name="GUC-SEQ-PAGE-COST"></a><tt class="VARNAME">seq_page_cost</tt> (<tt class="TYPE">floating point</tt>)</dt>
<dd><p>设置规划器计算一次顺序磁盘页面抓取的开销。默认值是 1.0 。</p></dd>
<dt><a name="GUC-RANDOM-PAGE-COST"></a><tt class="VARNAME">random_page_cost</tt> (<tt class="TYPE">floating point</tt>)</dt>
<dd><p>设置规划器计算一次非顺序磁盘页面抓取的开销。默认值是 4.0 。(相对于 <tt class="VARNAME">seq_page_cost</tt>)减少这个值将导致更倾向于使用索引扫描，而增加这个值将导致更倾向于使用顺序扫描。可以通过同时增加或减少这两个值来调整磁盘 I/O 相对于 CPU 的开销(在下面的参数中描述)。</p>
<div class="TIP">
<blockquote class="TIP">
<p><b>【提示】</b>虽然允许你将 <tt class="VARNAME">random_page_cost</tt> 设置的比 <tt class="VARNAME">seq_page_cost</tt> 小，但是物理上的实际情况并不受此影响。然而当所有数据库都位于内存中时，两者设置为相等是非常合理的，因为在此情况下，乱序抓取并不比顺序抓取开销更大。同样，在缓冲率很高的数据库上，你应当相对于 CPU 开销同时降低这两个值，因为获取内存中的页比通常情况下的开销小许多。</p>
</blockquote>
</div></dd>
<dt><a name="GUC-CPU-TUPLE-COST"></a><tt class="VARNAME">cpu_tuple_cost</tt> (<tt class="TYPE">floating point</tt>)</dt>
<dd><p>设置规划器计算在一次查询中处理一个数据行的开销。缺省是 0.01 。</p></dd>
<dt><a name="GUC-CPU-INDEX-TUPLE-COST"></a><tt class="VARNAME">cpu_index_tuple_cost</tt> (<tt class="TYPE">floating point</tt>)</dt>
<dd><p>设置规划器计算在一次索引扫描中处理每条索引行的开销。缺省是 0.005 。</p></dd>
<dt><a name="GUC-CPU-OPERATOR-COST"></a><tt class="VARNAME">cpu_operator_cost</tt> (<tt class="TYPE">floating point</tt>)</dt>
<dd><p>设置规划器计算在一次查询中执行一个操作符或函数的开销。缺省是 0.0025 。</p></dd>
<dt><a name="GUC-EFFECTIVE-CACHE-SIZE"></a><tt class="VARNAME">effective_cache_size</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>为规划器设置在一次索引扫描中可用的磁盘缓冲区的有效大小。这个参数会在计算一个索引的预计开销值的时候加以考虑。更高的数值会导致更可能使用索引扫描，更低的数值会导致更有可能选择顺序扫描。在设置这个参数的时候，你还应该考虑 PostgreSQL 的数据文件会使用的共享缓冲区和内核的磁盘缓冲区。另外，还要考虑预计会使用不同索引的并发查询数目，因为它们必须共享可用的内存空间。这个参数对 PostgreSQL 分配的共享内存大小没有影响，它也不会使用内核磁盘缓冲，它只用于估算。数值是用磁盘页来计算的，通常每个页面是 8192 字节。缺省是 16384(<tt class="LITERAL">128MB</tt>)。</p></dd>
</dl>
</div>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="RUNTIME-CONFIG-QUERY-GEQO">17.6.3. 基因查询优化器</a></h2>
<div class="VARIABLELIST">
<dl>
<dt><a name="GUC-GEQO"></a><tt class="VARNAME">geqo</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>允许或禁止基因查询优化，这是一种试图不通过穷举搜索来实现查询规划的算法。缺省是允许。<tt class="VARNAME">geqo_threshold</tt> 变量提供了一种为特定类别的查询关闭 GEQO 的更精细方法。</p></dd>
<dt><a name="GUC-GEQO-THRESHOLD"></a><tt class="VARNAME">geqo_threshold</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>只有当涉及的 <tt class="LITERAL">FROM</tt> 关系数量至少有这么多个的时候，才使用基因查询优化。对于数量小于此值的查询，也许使用判定性的穷举搜索更有效。但是对于有许多表的查询，规划器做判断要花很多时间。缺省是 12 。请注意一个 <tt class="LITERAL">FULL OUTER JOIN</tt> 构造只算一个 <tt class="LITERAL">FROM</tt> 项。</p></dd>
<dt><a name="GUC-GEQO-EFFORT"></a><tt class="VARNAME">geqo_effort</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>控制 GEQO 里规划时间和查询规划的有效性之间的平衡。这个变量必须是一个范围从 1 到 10 的整数。缺省值是 5 。大的数值增加花在进行查询规划上面的时间，但是也很可能会提高选中更有效的查询规划的几率。</p>
<p><tt class="VARNAME">geqo_effort</tt> 实际上并没有直接干什么事情；只是用于计算其它那些影响 GEQO 行为变量的缺省值(在下面描述)。如果你愿意，你可以手工设置其它参数。</p></dd>
<dt><a name="GUC-GEQO-POOL-SIZE"></a><tt class="VARNAME">geqo_pool_size</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>控制 GEQO 使用的池大小。池大小是基因全体中的个体数量。它必须至少是 2 ，并且有用的数值通常在 100 和 1000 之间。如果把它设置为零(缺省)，那么就会基于 <tt class="VARNAME">geqo_effort</tt> 和查询中表的数量选取一个合适的值。</p></dd>
<dt><a name="GUC-GEQO-GENERATIONS"></a><tt class="VARNAME">geqo_generations</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>控制 GEQO 使用的子代数目。子代的意思是算法的迭代次数。它必须至少是 1 ，有用的值范围和池大小相同。如果设置为零(缺省)，那么将基于 <tt class="VARNAME">geqo_pool_size</tt> 选取合适的值。</p></dd>
<dt><a name="GUC-GEQO-SELECTION-BIAS"></a><tt class="VARNAME">geqo_selection_bias</tt> (<tt class="TYPE">floating point</tt>)</dt>
<dd><p>控制GEQO使用的选择性偏好。选择性偏好是在一个种群中的选择性压力。数值可以是 1.5 到 2.0 之间；缺省是 2.0 。</p></dd>
</dl>
</div>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="RUNTIME-CONFIG-QUERY-OTHER">17.6.4. 其它规划器选项</a></h2>
<div class="VARIABLELIST">
<dl>
<dt><a name="GUC-DEFAULT-STATISTICS-TARGET"></a><tt class="VARNAME">default_statistics_target</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>为没有用 <tt class="COMMAND">ALTER TABLE SET STATISTICS</tt> 设置字段相关目标的表中其它字段设置缺省统计目标。更大的数值增加了 <tt class="COMMAND">ANALYZE</tt> 所需要的时间，但是可能会改善规划器的估计质量。缺省值是 10 。有关 PostgreSQL 的查询规划器使用的统计的更多信息，请参考<a href="planner-stats.html">节13.2</a>。</p></dd>
<dt><a name="GUC-CONSTRAINT-EXCLUSION"></a><tt class="VARNAME">constraint_exclusion</tt> (<tt class="TYPE">boolean</tt>)</dt>
<dd><p>打开或者关闭查询规划器使用表约束限制表访问的特性。缺省是 <tt class="LITERAL">off</tt></p>
<p>如果这个参数是 <tt class="LITERAL">on</tt> ，那么规划器用查询条件和 <tt class="LITERAL">CHECK</tt> 约束进行比较，并且在查询条件和约束冲突的情况下，忽略对表的扫描。比如：</p>
<pre class="PROGRAMLISTING">CREATE TABLE parent(key integer, ...);
CREATE TABLE child1000(check (key between 1000 and 1999)) INHERITS(parent);
CREATE TABLE child2000(check (key between 2000 and 2999)) INHERITS(parent);
...
SELECT * FROM parent WHERE key = 2400;</pre>
<p>在打开约束排除的时候，这个 <tt class="COMMAND">SELECT</tt> 将完全不会扫描 <tt class="STRUCTNAME">child1000</tt> 。这样可以在使用继承制作分区表的时候提高性能。</p>
<p>目前，<tt class="VARNAME">constraint_exclusion</tt> 缺省被关闭，因为如果查询规划被缓冲了，那么就会有不正确结果的风险：如果一个表约束改变或者删除了，那么前面生成的查询计划现在就可能是错的了，而又没有内置的机制强制重新规划。另外一个把它关闭的原因是约束检查相对来说开销还是比较大的，在很多环境下它并不能节约开销。只是在你实际上使用了从设计上就利用这个特性的表分区的场合下，我们才推荐打开它。</p>
<p>参考<a href="ddl-partitioning.html">节5.9</a>获取有关使用约束排除和分区的更多信息。</p></dd>
<dt><a name="GUC-FROM-COLLAPSE-LIMIT"></a><tt class="VARNAME">from_collapse_limit</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>如果生成的 <tt class="LITERAL">FROM</tt> 列表不超过这个限制的项数，规划器将把子查询融合到上层查询。小的数值降低规划的时间，但是可能会生成差些的查询计划。缺省是 8 。通常，把它限制在小于 <a href="runtime-config-query.html#GUC-GEQO-THRESHOLD">geqo_threshold</a> 的数值是比较明智的。更多信息请查看<a href="explicit-joins.html">节13.3</a>。</p></dd>
<dt><a name="GUC-JOIN-COLLAPSE-LIMIT"></a><tt class="VARNAME">join_collapse_limit</tt> (<tt class="TYPE">integer</tt>)</dt>
<dd><p>如果得出的列表不超过这个数目的项，那么规划器将把除 <tt class="LITERAL">FULL JOIN</tt> 之外的 <tt class="LITERAL">JOIN</tt> 构造抹平到 <tt class="LITERAL">FROM</tt> 列表项中。小的数值降低规划的时间，但是可能会生成差些的查询计划。</p>
<p>缺省时，这个值和 <tt class="VARNAME">from_collapse_limit</tt> 相同，这样适合大多数场合。把它设置为 1 则避免任何 <tt class="LITERAL">JOIN</tt> 的融合，这样就将明确使用语句中的连接顺序。查询优化器并不是总能选取最优的连接顺序；高级用户可以选择暂时把这个变量设置为 1 ，然后明确地声明他们需要的连接顺序。更多信息参见<a href="explicit-joins.html">节13.3</a>。</p></dd>
</dl>
</div>
</div>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="runtime-config-wal.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="runtime-config-logging.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">预写式日志</td><td width="34%" align="center" valign="top"><a href="runtime-config.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">错误报告和日志</td></tr>
</table>
</div>
</body></html>